{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# 235. Lowest Common Ancestor of a Binary Search Tree\n",
    "Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.\n",
    "\n",
    "According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow **a node to be a descendant of itself**).”\n",
    "\n",
    "Given binary search tree:  root = [6,2,8,0,4,7,9,null,null,3,5]\n",
    "\n",
    "\n",
    "<div align=\"center\">\n",
    "    <img src=\"./images/binarysearchtree_improved.png\" width=\"20%\">\n",
    "</div>\n",
    "\n",
    "    Example 1:\n",
    "        Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8\n",
    "        Output: 6\n",
    "        Explanation: The LCA of nodes 2 and 8 is 6.\n",
    "\n",
    "    Example 2:\n",
    "        Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4\n",
    "        Output: 2\n",
    "        Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.\n",
    "\n",
    "\n",
    "Constraints:\n",
    "    1. All of the nodes' values will be unique.\n",
    "    2. p and q are different and both values will exist in the BST."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from typing import List\n",
    "\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "class TreeNode:\n",
    "    def __init__(self, x):\n",
    "        self.val = x\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:\n",
    "        def getPath(root: TreeNode, target: TreeNode) -> List[TreeNode]:\n",
    "            path = list()\n",
    "            node = root\n",
    "            while node != target:\n",
    "                path.append(node)\n",
    "                if target.val < node.val:\n",
    "                    node = node.left\n",
    "                else:\n",
    "                    node = node.right\n",
    "            path.append(node)\n",
    "            return path\n",
    "        path_p = getPath(root, p)\n",
    "        path_q = getPath(root, q)\n",
    "        ancestor = None\n",
    "        for u, v in zip(path_p, path_q):\n",
    "            if u == v:\n",
    "                ancestor = u\n",
    "            else:\n",
    "                break\n",
    "        return ancestor\n",
    "\n",
    "\n",
    "S = Solution()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": true
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "root = TreeNode(6)\n",
    "root.left = TreeNode(2)\n",
    "root.right = TreeNode(8)\n",
    "root.left.left = TreeNode(0)\n",
    "root.left.right = TreeNode(4)\n",
    "root.left.right.left = TreeNode(3)\n",
    "root.left.right.right = TreeNode(5)\n",
    "root.right.left = TreeNode(7)\n",
    "root.right.right = TreeNode(9)\n",
    "p = TreeNode(2)\n",
    "q = TreeNode(8)\n",
    "print(S.lowestCommonAncestor(root, p, q))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": true
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# Definition for a binary tree node.\n",
    "class TreeNode:\n",
    "    def __init__(self, x):\n",
    "        self.val = x\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:\n",
    "        ancestor = root\n",
    "        while True:\n",
    "            if p.val < ancestor.val and q.val < ancestor.val:\n",
    "                ancestor = ancestor.left\n",
    "            elif p.val > ancestor.val and q.val > ancestor.val:\n",
    "                ancestor = ancestor.right\n",
    "            else:\n",
    "                break\n",
    "        return ancestor\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}